﻿using System;
using System.Web;
using System.ComponentModel;
using System.Net.Sockets;
using System.Collections.Generic; 

    public class TcpMappingItem:IDisposable 
    {

        static public TcpMappingItem Create(Guid key,string server,int port)
        {
            TcpClient tc =null ;
            try
            {
                tc = new TcpClient(server, port);

            }
            catch { }
     

            if (tc != null)
            {
                return new TcpMappingItem() { Key = key, Server = server, Port = port, LastActive = System.DateTime.Now,  TcpStream = tc.GetStream()  };
            }
            else { return null; }
        
        }



        public    TcpMappingItem()
        {           
            
        }

        public Guid  Key
        {
            get;
            private  set;

        }
        System.Net.Sockets.NetworkStream _TcpStream;
        public System.Net.Sockets.NetworkStream  TcpStream
        {
            get
            {
                return _TcpStream;
            }
            set
            {
                if (TcpStream != null)
                {
                    TcpStream.Close();
                }
                _TcpStream = value;
                var bts=new byte[4096];
                TcpStream.BeginRead
                    (
                        bts,
                        0,
                        bts.Length,
                        new AsyncCallback(ReceivedData),
                        bts
                    );

            }
        }
        public event EventHandler  Received ;
        void ReceivedData(IAsyncResult ia)
        {
            LastActive = DateTime.Now;
            var bts = (byte[])ia.AsyncState;
            var length = TcpStream.EndRead(ia );

            var nbts = new byte[length];
            Array.Copy(bts, nbts, length);
            _ReceivedPool.AddLast(nbts);
            Received(this, null);
            TcpStream.BeginRead
              (
                  bts,
                  0,
                  bts.Length,
                  new AsyncCallback(ReceivedData),
                  bts
              );

        }
        void SentData()
        {
            LastActive = DateTime.Now;
            var bts=_SendPool.First.Value ;
            _SendPool.RemoveFirst();
            if (_SendPool.Count >0)
                TcpStream.BeginWrite(bts, 0, bts.Length, new AsyncCallback(ia => SentData()), null); 

        }



        public int Port
        {
            get;
            private set;

        }

        public string Server
        {
            get;
            private set;
        }

        public DateTime LastActive
        {
            get;
            private set;
        }

        private System.Collections.Generic.LinkedList<Byte[]> _ReceivedPool = new System.Collections.Generic.LinkedList<byte[]>();
        private System.Collections.Generic.LinkedList<Byte[]> _SendPool = new System.Collections.Generic.LinkedList<byte[]>();

        public void SendBytes(byte[] buffer)
        {
            _ReceivedPool.AddLast(buffer);
            if (_ReceivedPool.Count == 0)
            {
                SentData();
            
            }
        }
        /// <summary>
        /// 得到一个
        /// </summary>
        /// <returns>是否还有剩余</returns>
        public bool ReceiveBytes(out byte [] buffer)
        {
            buffer = null;
            if (_ReceivedPool.Count == 0) return false;

            lock (_ReceivedPool)
            {
                byte[] received = null;
                if (_ReceivedPool.First.Value.Length > 64 * 1024)
                {
                    received = _ReceivedPool.FrontCutNodesFromNodeLists(64 * 1024);
                }
                else
                { 
                    received=_ReceivedPool.First .Value ;
                    _ReceivedPool.RemoveFirst();
                }
                buffer = received;
            }
            return  _ReceivedPool .Count !=0;
        }

        #region IDisposable Members

        public void Dispose()
        {
            if (TcpStream != null)
            {
                TcpStream.Dispose();
                TcpStream = null;

            }
        }

        #endregion

      
    }
